#include <stdio.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/wait.h>

#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#define MSG_TYPE_USR1 1 
#define MSG_TYPE_USR2 2 
#define MSG_TYPE_USR3 3 

// 定义消息队列中的消息结构体类型 MSG
typedef struct {
    long mtype; // 消息类型, 可选值 MSG_TYPE_USR1/2/3
    char mtitle[128]; // 消息标题 
    char mcontent[1024]; // 消息的内容
} MSG;

int main(int argc, char const *argv[])
{
    //1. 获取IPC键值KEY
    key_t k = ftok("/home/disen/syscode", 4);
    // 2. 获取或创建消息ID
    int msgid = msgget(k, IPC_CREAT|0644);

    // 3. 创建三个子进程
    int i = 0;
    for(;i<3; i++){
        if(fork() == 0) break;
    }
    if(i < 3){
        // 三个子进程相同的程序
        sleep(1);
        MSG msg = {i+1};
        // 将子进程号写入到title中
        sprintf(msg.mtitle, "%d 写数据", getpid());
        sprintf(msg.mcontent, "我是%d进程，准备向父进程(%d)写入大量数据", getpid(), getppid());

        msgsnd(msgid, &msg, sizeof(MSG), 0);
        _exit(0);
    }

    // 父进程
    MSG msg;
    bzero(&msg, sizeof(msg));
    for(int j=0;j<3; j++){
        ssize_t len = msgrcv(msgid, &msg, sizeof(MSG), -3, 0);
        printf("---- revc data ----\n");
        printf("msgType:  %ld\n", msg.mtype);
        printf("msgTitle: %s\n", msg.mtitle);
        printf("msgContent: %s\n", msg.mcontent);
    }

    while(wait(NULL) != -1);
    printf("--over--\n");
    return 0;
}
